package com.rzx.mybackend.utils;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.MethodInvoker;


/**
 * ReflectUtil
 *
 * @author renzhexian
 * @date 2025/10/13
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ReflectUtil {

    private final ApplicationContext applicationContext;

    /**
     * 通过Bean名称调用方法
     *
     * @param beanName Bean名称
     * @param methodName 方法名
     * @param args 方法参数
     * @return 方法返回值
     */
    public Object invoke(String beanName, String methodName, Object... args) {
        validateInputs(beanName, methodName);

        try {
            Object target = applicationContext.getBean(beanName);
            return invoke(target, methodName, args);
        } catch (BeansException e) {
            throw new RuntimeException("获取Bean失败: " + beanName, e);
        }
    }

    /**
     * 通过目标对象调用方法
     *
     * @param target 目标对象
     * @param methodName 方法名
     * @param args 方法参数
     * @return 方法返回值
     */
    public Object invoke(Object target, String methodName, Object... args) {
        validateInputs(target, methodName);

        try {
            MethodInvoker invoker = new MethodInvoker();
            invoker.setTargetObject(target);
            invoker.setTargetMethod(methodName);
            invoker.setArguments(args);
            invoker.prepare();

            Object result = invoker.invoke();
            log.debug("方法调用成功: {}.{}()",
                    target.getClass().getSimpleName(), methodName);

            return result;

        } catch (Exception e) {
            log.error("方法调用失败: {}.{}",
                    target.getClass().getSimpleName(), methodName, e);
            throw new RuntimeException("方法调用失败: " + methodName, e);
        }
    }

    private void validateInputs(String beanName, String methodName) {
        if (beanName == null || beanName.isEmpty()) {
            throw new IllegalArgumentException("Bean名称不能为空");
        }
        if (methodName == null || methodName.isEmpty()) {
            throw new IllegalArgumentException("方法名不能为空");
        }
    }

    private void validateInputs(Object target, String methodName) {
        if (target == null) {
            throw new IllegalArgumentException("目标对象不能为空");
        }
        if (methodName == null || methodName.isEmpty()) {
            throw new IllegalArgumentException("方法名不能为空");
        }
    }
}
